package algorithm3_v3;

import java.io.BufferedReader;
import java.io.FileReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Initialization {
	static Logger logger = LoggerFactory.getLogger(Initialization.class);

	private static HashMap<String, String> paramControl(String[] args) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("timeUnit", "500");
		params.put("processes", "processes");
		params.put("leader", "leader");
		params.put("incarnation", "incarnation");

		for (int i = 0; i < args.length; i++) {
			switch (args[i]) {
			case "-h":
			case "--help":
				System.out
						.println("-h,--help/n/t laguntza/n"
								+ "-u,--unit/n/t erabiliko den denbora lapsoa milisegundutan (lehenetsia 500ms)/n"
								+ "-p,--processes/n/t parte hartuko duten prozesuen fitxategiaren path-a/n (lehenetsia ./processes)"
								+ "Honako hauek sistema testeatzeko parametroak dira, ez erabili sistemaren prozesamentu normal bat nahi bada"
								+ "-l,--leader/n/t liderra gordeko duen fitxategiaren path-a/n (lehenetsia ./leader)"
								+ "-i,--incarnation/n/t incarnation gordeko duen fitxaegiaren path-a/n (lehenetsia ./incarnation)");
				break;
			case "-u":
			case "--unit":
				String timeUnit = args[i + 1];
				params.put("timeUnit", timeUnit);
				break;
			case "-p":
			case "--processes":
				String fileProcesses = args[i + 1];
				params.put("processes", fileProcesses);
				break;
			case "-l":
			case "--leader":
				String fileLeader = args[i + 1];
				params.put("leader", fileLeader);
				break;
			case "-i":
			case "--incarnation":
				String fileIncarnation = args[i + 1];
				params.put("incarnation", fileIncarnation);
				break;
			}
		}
		return params;
	}

	public static ArrayList<String> getProcesses(String fileProcesses) {
		ArrayList<String> processes = new ArrayList<String>();
		boolean find = false;
		try {
			String machineName = InetAddress.getLocalHost().getHostName();
			BufferedReader processFile = new BufferedReader(new FileReader(
					fileProcesses));
			String line = processFile.readLine();
			while (line != null) {

				if (!(line.compareTo(machineName) == 0))
					processes.add(line);
				else
					find = true;
				line = processFile.readLine();
			}
			processFile.close();
			if (!find)
				throw new Exception(
						"ERROREA: prozesu hau ez dago prozesu fitxategian");
		} catch (Exception e) {
			logger.info("ERROREA:prozesu fitxategia irakurtzean");
			e.printStackTrace();
			System.exit(1);
		}

		return processes;
	}

	public static void main(String[] args) {
		SystemInfo info = SystemInfo.INSTANCE;
		ScheduledExecutorService scheduler = Executors
				.newScheduledThreadPool(2);
		HashMap<String, String> params = paramControl(args);
		info.externalProcesses.addAll(getProcesses(params.get("processes")));
		info.processes.addAll(getProcesses(params.get("processes")));
		try {
			info.processes.add(InetAddress.getLocalHost().getHostName());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		info.timeUnit[0] = Integer.parseInt(params.get("timeUnit"));
		// String processName = ManagementFactory.getRuntimeMXBean().getName();
		// -> makina izena eta prozesu zenbakia, baiño inetaddress ibilita
		// dns-ko izena(nahiz da eztaukeun prozesu izenik)
		info.leader.delete(0, info.leader.length());
		info.timeout[0] = System.currentTimeMillis();
		info.p_ts[0] = System.currentTimeMillis();
		info.min_ts[0] = info.p_ts[0];
		ScheduledExecutorService task3 = Executors
				.newSingleThreadScheduledExecutor();
		ScheduledFuture<String> task3Future = null;
		task3Future = task3.schedule(new Task3(), info.timeout[0],
				TimeUnit.MILLISECONDS);
		scheduler.schedule(new Task1(task3Future, task3), info.timeout[0],
				TimeUnit.MILLISECONDS);// info.timeUnit+info.incarnation[0]??
		scheduler.submit(new Task2(task3Future, task3));

	}
}
